using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace Comteck.Winforms.Utils {
  public class FtpHelper {

    /// <summary>
    /// 判断FTP是否连通
    /// </summary>
    /// <param name="ftpPath">FTP地址</param>
    /// <param name="ftpUserId">FTP用户名</param>
    /// <param name="ftpPassword">FTP密码</param>
    /// <param name="timeOut">超时时间(默认3秒)</param>
    /// <returns>
    /// code：1成功 0失败
    /// message：返回信息
    /// </returns>
    public static AjaxResponse CheckFtpConnect(string ftpPath, string ftpUserId, string ftpPassword, int timeOut = 3) {
      var result = new AjaxResponse();

      // 根据uri创建FtpWebRequest对象 
      FtpWebRequest reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpPath));
      reqFTP.Credentials = new NetworkCredential(ftpUserId, ftpPassword);
      reqFTP.UsePassive = true; // 使用被动式
      reqFTP.KeepAlive = false;// 默认为true，连接不会被关闭
      reqFTP.Method = WebRequestMethods.Ftp.ListDirectory;
      reqFTP.UseBinary = true;

      try {
        FtpWebResponse ftpResponse = (FtpWebResponse)reqFTP.GetResponse();
        ftpResponse.Close();
        result.Message = "成功";
        result.Code = 1;
      } catch (Exception ex) {
        result.Message = $"失败，{ex.Message}";
        result.Code = 0;
      }

      return result;
    }

    /// <summary>
    /// 校验FTP服务器上是否已存在文件
    /// </summary>
    /// <param name="localFile">本地文件</param>
    /// <param name="ftpPath">FTP地址</param>
    /// <param name="ftpUserId">FTP用户名</param>
    /// <param name="ftpPassword">FTP密码</param>
    /// <param name="timeOut">超时时间(默认3秒)</param>
    /// <returns>
    /// code：1存在 2不存在 0失败
    /// message：返回信息
    /// </returns>
    public static AjaxResponse RemoteFileExists(string localFile, string ftpPath, string ftpUserId, string ftpPassword, int timeOut = 3) {
      var result = new AjaxResponse();

      FtpWebRequest reqFTP = (FtpWebRequest)WebRequest.Create(new Uri(ftpPath + Path.GetFileName(localFile)));
      reqFTP.Credentials = new NetworkCredential(ftpUserId, ftpPassword); // ftp用户名和密码  
      reqFTP.UsePassive = true; // 使用被动式
      reqFTP.KeepAlive = false;// 默认为true，连接不会被关闭
      reqFTP.Method = WebRequestMethods.Ftp.ListDirectory; // 读取文件名

      var fileNames = new List<string>();

      try {
        var response = reqFTP.GetResponse();
        var reader = new StreamReader(response.GetResponseStream(), Encoding.Default);

        string line = reader.ReadLine();
        while (line != null) {
          fileNames.Add(line);
          line = reader.ReadLine();
        }

        reader.Close();
        response.Close();

        if (fileNames.Contains(localFile)) {
          result.Message = "存在";
          result.Code = 1;
        }
        else {
          result.Message = "不存在";
          result.Code = 2;
        }

      } catch (Exception ex) {
        result.Message = $"失败，{ex.Message}";
        result.Code = 0;
      }

      return result;
    }

    /// <summary>
    /// 上传文件
    /// </summary>
    /// <param name="localFile">本地文件</param>  
    /// <param name="ftpPath">FTP地址</param>
    /// <param name="ftpUserId">FTP用户名</param>
    /// <param name="ftpPassword">FTP密码</param>
    /// <param name="timeOut">超时时间(默认3秒)</param>
    /// <return>返回上传结果：返回标识符、提示信息、上传后的文件名</return>
    public static AjaxResponse UploadFile(string localFile, string ftpPath, string ftpUserId, string ftpPassword, int timeOut = 3) {
      var result = new AjaxResponse();

      if (!File.Exists(localFile)) {
        result.Code = 0;
        result.Message = $"本地文件：{localFile} 不存在！";
        return result;
      }

      var fileInfo = new FileInfo(localFile);
      var reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpPath + result.Data));// 根据uri创建FtpWebRequest对象   
      reqFTP.Credentials = new NetworkCredential(ftpUserId, ftpPassword);// ftp用户名和密码  
      reqFTP.KeepAlive = false;// 默认为true，连接不会被关闭
      reqFTP.Method = WebRequestMethods.Ftp.UploadFile;// 指定执行什么命令  
      reqFTP.UseBinary = true;// 指定数据传输类型  
      reqFTP.ContentLength = fileInfo.Length;// 上传文件时通知服务器文件的大小 
      reqFTP.Timeout = timeOut * 1000; // 超时时间

      int buffLength = 2048;// 缓冲大小设置为2kb
      byte[] buff = new byte[buffLength];
      int contentLen;

      try {
        // 打开一个文件流 (System.IO.FileStream) 去读上传的文件  
        using (FileStream fs = fileInfo.OpenRead()) {
          using (Stream stream = reqFTP.GetRequestStream()) // 把上传的文件写入流  
          {
            // 每次读文件流的2kb 
            while ((contentLen = fs.Read(buff, 0, buffLength)) > 0) {
              // 把内容从file stream 写入 upload stream  
              stream.Write(buff, 0, contentLen);
            }
          }
        }

        result.Message = "成功";
      } catch (Exception ex) {
        result.Code = 0;
        result.Message = $"失败，{ex.Message}";

      }
      return result;
    }

    /// <summary>
    /// 删除文件
    /// </summary>
    /// <param name="localFile">本地文件</param>
    /// <param name="ftpPath">FTP地址</param>
    /// <param name="ftpUserId">FTP用户名</param>
    /// <param name="ftpPassword">FTP密码</param>
    /// <param name="timeOut">超时时间(默认3秒)</param>
    /// <returns>
    /// code：1存在 2不存在 0失败
    /// message：返回信息
    /// </returns>
    public static AjaxResponse DeleteFile(string localFile, string ftpPath, string ftpUserId, string ftpPassword, int timeOut = 3) {
      var result = new AjaxResponse();

      FtpWebRequest reqFTP = (FtpWebRequest)WebRequest.Create(new Uri(ftpPath + Path.GetFileName(localFile)));
      reqFTP.Credentials = new NetworkCredential(ftpUserId, ftpPassword); // ftp用户名和密码  
      reqFTP.UsePassive = true; // 使用被动式
      reqFTP.KeepAlive = false;// 默认为true，连接不会被关闭
      reqFTP.Method = WebRequestMethods.Ftp.DeleteFile; // 删除文件

      try {
        FtpWebResponse ftpResponse = (FtpWebResponse)reqFTP.GetResponse();
        ftpResponse.Close();
        result.Message = "成功";
        result.Code = 1;
      } catch (Exception ex) {
        result.Message = $"失败，{ex.Message}";
        result.Code = 0;
      }

      return result;
    }
  }
}
